home *** CD-ROM | disk | FTP | other *** search
/ Giga Games 1 / Giga Games.iso / net / usenet / volume6 / suntetrs.1 < prev    next >
Encoding:
Internet Message Format  |  1989-07-06  |  37.8 KB

  1. Path: uunet!tektronix!tekgen!tekred!games
  2. From: games@tekred.CNA.TEK.COM
  3. Newsgroups: comp.sources.games
  4. Subject: v06i042:  sun-tetris1 - tetris under SunView (first version)
  5. Message-ID: <3800@tekred.CNA.TEK.COM>
  6. Date: 3 Apr 89 20:15:55 GMT
  7. Sender: billr@tekred.CNA.TEK.COM
  8. Lines: 1254
  9. Approved: billr@saab.CNA.TEK.COM
  10.  
  11. Submitted-by: Rick Iwamoto <iwamoto@sun.com>
  12. Posting-number: Volume 6, Issue 42
  13. Archive-name: sun-tetris1
  14.  
  15.     [The other day I received two implementations of tetris under
  16.      SunView.  This is the first one.  They both use color (colour)
  17.      on machines that support it.  I have tested them both on a B&W
  18.      Sun 3/60, SunOS 3.5. The second one follows in the next posting. -br]
  19.  
  20. #! /bin/sh
  21. # This is a shell archive.  Remove anything before this line, then unpack
  22. # it by saving it into a file and typing "sh file".  To overwrite existing
  23. # files, type "sh file -c".  You can also feed this as standard input via
  24. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  25. # will see the following message at the end:
  26. #        "End of archive 1 (of 1)."
  27. # Contents:  README Makefile suntetris.6 suntetris.c suntetris.h
  28. #   suntetris.icon suntetris_pw.c
  29. # Wrapped by billr@saab on Mon Apr  3 13:11:41 1989
  30. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  31. if test -f 'README' -a "${1}" != "-c" ; then 
  32.   echo shar: Will not clobber existing file \"'README'\"
  33. else
  34. echo shar: Extracting \"'README'\" \(2204 characters\)
  35. sed "s/^X//" >'README' <<'END_OF_FILE'
  36. X
  37. X
  38. X
  39. X
  40. X                SUNTETRIS
  41. X
  42. X
  43. XTo install, change the highscore filename in the Makefile and type "make".
  44. X
  45. X
  46. XPlaying the game
  47. X----------------
  48. X
  49. XSelecting the level and height of random blocks:
  50. X
  51. X    Use the '0'-'9' keys, the cursor keys, or 'h', 'j', 'k', 'l' as in "vi"
  52. X    to select the level, hit "return"
  53. X    Select the height, and hit "return" to begin the game.
  54. X
  55. X
  56. XThe game controls:
  57. X
  58. X    'j' R10 or the left mouse button makes the figure shift left
  59. X
  60. X    'k' R11 or the middle mouse button makes the figure rotate
  61. X    (counter clockwise)
  62. X
  63. X    'l' R12 or the right mouse button makes the figure shift right
  64. X
  65. X    spacebar or R14 makes the figure drop down
  66. X
  67. X    'u' or R8 increases level
  68. X
  69. X    'q' quits the game at any time
  70. X
  71. X    When your cursor leaves the window, the game will pause.
  72. X    When your cursor enters the window, the game will resume.
  73. X
  74. XWhen the game ends, the high scores are displayed until the "return" key
  75. Xis pressed.
  76. X
  77. X
  78. XNote:
  79. XIn order to use the R(n) keys (the cursor keys), they must be emitting Sunview
  80. Xfunction codes, not ANSI escape sequences.  This can be changed by using
  81. Xdefaultsedit and selecting the "Input" menu.
  82. X
  83. X
  84. X
  85. XThe Game
  86. X--------
  87. X
  88. XDifferent shaped figures fall from the top of the playing area to the bottom,
  89. Xwhere they come to rest.  When a figure comes to rest and it completes a solid
  90. Xrow of blocks across the playing area, the row disappears and everything above
  91. Xit shifts down.  The game ends when the figures pile up to the very top of the
  92. Xplaying area.
  93. X
  94. XThe object of the game is to manuever the falling figure by moving it left,
  95. Xright, and by rotating it to avoid having the figures pile up too high.  A
  96. Xfigure may be dropped to a resting position at any time for more points.  Your
  97. Xscore depends on the current level and the height at which the figure lands
  98. Xor is dropped from.  The level (speed) increases when the number of rows
  99. Xdeleted reaches certain levels.
  100. X
  101. X
  102. X
  103. XComments
  104. X--------
  105. X
  106. XI tried to make this look and feel exactly like the PC version, with the
  107. Xexception of the different background pictures and the "Next block" indicator,
  108. Xwhich didn't work on the PC version that I saw.  The scoring system may
  109. Xnot be the same.
  110. X
  111. X
  112. XReport any bugs to iwamoto@sun.com.
  113. X
  114. X-Rick Iwamoto
  115. END_OF_FILE
  116. if test 2204 -ne `wc -c <'README'`; then
  117.     echo shar: \"'README'\" unpacked with wrong size!
  118. fi
  119. # end of 'README'
  120. fi
  121. if test -f 'Makefile' -a "${1}" != "-c" ; then 
  122.   echo shar: Will not clobber existing file \"'Makefile'\"
  123. else
  124. echo shar: Extracting \"'Makefile'\" \(453 characters\)
  125. sed "s/^X//" >'Makefile' <<'END_OF_FILE'
  126. X# @(#)Makefile    1.5 3/22/89
  127. XOBJS = suntetris.o suntetris_pw.o
  128. XCFLAGS = -O
  129. XLIBS = -lsuntool -lsunwindow -lpixrect
  130. X
  131. X# Change this to desired highscore file before compiling
  132. X# i.e. "/usr/games/suntetris.hs"
  133. XHIGHSCOREFILE = /usr/net/games/lib/suntetris.hs
  134. X
  135. Xsuntetris: $(OBJS)
  136. X    cc $(CFLAGS) $(OBJS) -o suntetris $(LIBS)
  137. X
  138. Xsuntetris.o: suntetris.h
  139. X
  140. Xsuntetris_pw.o: suntetris.h suntetris_pw.c
  141. X    cc $(CFLAGS) -c -DHIGHSCOREFILE=\"$(HIGHSCOREFILE)\" suntetris_pw.c
  142. END_OF_FILE
  143. if test 453 -ne `wc -c <'Makefile'`; then
  144.     echo shar: \"'Makefile'\" unpacked with wrong size!
  145. fi
  146. # end of 'Makefile'
  147. fi
  148. if test -f 'suntetris.6' -a "${1}" != "-c" ; then 
  149.   echo shar: Will not clobber existing file \"'suntetris.6'\"
  150. else
  151. echo shar: Extracting \"'suntetris.6'\" \(2146 characters\)
  152. sed "s/^X//" >'suntetris.6' <<'END_OF_FILE'
  153. X.TH SUNTETRIS 6
  154. X.SH NAME
  155. Xsuntetris - tetris for SunView
  156. X.SH SYNOPSIS
  157. Xsuntetris [bw]
  158. X.SH DESCRIPTION
  159. X.SS Options
  160. XIf any arguments are supplied, black and white rendition is forced
  161. X(applies to color monitors only).
  162. X.SS Playing the game
  163. X.LP
  164. XSelecting the level and height of random blocks:
  165. X.IP
  166. XUse the '0'-'9' keys, the cursor keys, or 'h', 'j', 'k', 'l' as in "vi"
  167. Xto select the level, hit "return".
  168. XSelect the height using cursor keys or hjkl, and hit "return" to begin
  169. Xthe game.
  170. X.LP
  171. XThe game controls:
  172. X.IP
  173. X\&'j' R10 or the left mouse button makes the figure shift left
  174. X.IP
  175. X\&'k' R11 or the middle mouse button makes the figure rotate
  176. X(counter clockwise)
  177. X.IP
  178. X\&'l' R12 or the right mouse button makes the figure shift right
  179. X.IP
  180. Xspacebar or R14 makes the figure drop down
  181. X.IP
  182. X\&'u' or R8 increases level
  183. X.IP
  184. X\&'q' quits the game at any time
  185. X.IP
  186. XWhen your cursor leaves the window, the game will pause.
  187. XWhen your cursor enters the window, the game will resume.
  188. X.LP
  189. XWhen the game ends, the high scores are displayed until the "return" key
  190. Xis pressed.
  191. X.SS The Game
  192. X.LP
  193. XDifferent shaped figures fall from the top of the playing area to the bottom,
  194. Xwhere they come to rest.  When a figure comes to rest and it completes a solid
  195. Xrow of blocks across the playing area, the row disappears and everything above
  196. Xit shifts down.  The game ends when the figures pile up to the very top of the
  197. Xplaying area.
  198. X.LP
  199. XThe object of the game is to manuever the falling figure by moving it left,
  200. Xright, and by rotating it to avoid having the figures pile up too high.  A
  201. Xfigure may be dropped to a resting position at any time for more points.  Your
  202. Xscore depends on the current level and the height at which the figure lands
  203. Xor is dropped from.  The level (speed) increases when the number of rows
  204. Xdeleted reaches certain levels.
  205. X.SH FILES
  206. Xsuntetris.hs - high score file
  207. X.SH AUTHOR
  208. XRick Iwamoto (iwamoto@sun.com).
  209. X.SH COMMENTS
  210. XI tried to make this look and feel exactly like the PC version, with the
  211. Xexception of the different background pictures and the "Next block" indicator,
  212. Xwhich didn't work on the PC version that I saw.  The scoring system may
  213. Xnot be the same.
  214. END_OF_FILE
  215. if test 2146 -ne `wc -c <'suntetris.6'`; then
  216.     echo shar: \"'suntetris.6'\" unpacked with wrong size!
  217. fi
  218. # end of 'suntetris.6'
  219. fi
  220. if test -f 'suntetris.c' -a "${1}" != "-c" ; then 
  221.   echo shar: Will not clobber existing file \"'suntetris.c'\"
  222. else
  223. echo shar: Extracting \"'suntetris.c'\" \(9581 characters\)
  224. sed "s/^X//" >'suntetris.c' <<'END_OF_FILE'
  225. X#ifndef lint
  226. Xstatic char sccsid[] = "@(#)suntetris.c    1.17 3/23/89";
  227. X#endif
  228. X
  229. X/*
  230. X *  Copyright 1989, Rick Iwamoto iwamoto@sun.com
  231. X *  Permission is given to copy and distribute for non-profit purposes.
  232. X */
  233. X
  234. X#include <stdio.h>
  235. X#include <suntool/sunview.h>
  236. X#include <suntool/canvas.h>
  237. X#include "suntetris.h"
  238. X
  239. Xstatic short icon_image[] = {
  240. X#include "suntetris.icon"
  241. X};
  242. XDEFINE_ICON_FROM_IMAGE (tetris_icon, icon_image);
  243. X
  244. XCanvas canvas;
  245. X
  246. Xstatic int my_client_object;
  247. Xstatic int *me = &my_client_object;
  248. Xstatic int paused = 0, selht = 0, height = 0;
  249. Xstatic int level, lines, score, make_new_fig;
  250. Xstatic int current_color, current_fig, current_rot, current_x, current_y;
  251. Xstatic struct itimerval timer;
  252. X
  253. Xvoid init_pw (), draw_board (), rand_blocks (), draw_figure (), draw_score ();
  254. Xvoid close_board (), display_choices (), display_hs (), update_hs ();
  255. Xvoid select_level (), select_height ();
  256. Xvoid mark_board ();
  257. Xint safe_move ();
  258. X
  259. Xstatic Notify_value figure_dropper ();
  260. Xstatic void new_figure (), place_figure ();
  261. Xstatic void game_setup (), start_game (), game_over (), drop_down ();
  262. Xstatic void start_timer (), stop_timer ();
  263. Xstatic void game_control_proc (), choose_level ();
  264. Xstatic void choose_height (), wait_for_return ();
  265. X
  266. X
  267. X/*
  268. X    4 canvas input event routines
  269. X
  270. X    1) choose_level ()
  271. X    player chooses level to start at
  272. X    2) choose_height ()
  273. X    player chooses height to start at
  274. X    3) game_control_proc ()
  275. X    game controls (move blocks around etc.)
  276. X    4) wait_for_return ()
  277. X    game waits for player to hit return while displaying highscores
  278. X*/
  279. X
  280. Xmain (argc, argv)
  281. Xint argc;
  282. Xchar **argv;
  283. X{
  284. X    Frame frame;
  285. X
  286. X    frame = window_create (0, FRAME,
  287. X        FRAME_LABEL, argv[0],
  288. X        FRAME_ICON, &tetris_icon,
  289. X        0);
  290. X    canvas = window_create (frame, CANVAS,
  291. X         CANVAS_RETAINED, FALSE,
  292. X         WIN_WIDTH, 400,
  293. X         WIN_HEIGHT, 400,
  294. X         WIN_CONSUME_PICK_EVENT, WIN_IN_TRANSIT_EVENTS,
  295. X         WIN_CONSUME_KBD_EVENTS, WIN_ASCII_EVENTS, WIN_RIGHT_KEYS, 0,
  296. X         0);
  297. X    window_fit (frame);
  298. X    init_pw (argc > 1);    /* force b&w operation if any arguments exist */
  299. X    window_set (canvas, CANVAS_RETAINED, TRUE, 0);
  300. X    srandom (getpid ());
  301. X
  302. X    game_setup ();
  303. X    window_main_loop (frame);
  304. X}
  305. X
  306. X
  307. X/* figure_dropper does the periodic downward moving of the figures */
  308. Xstatic Notify_value
  309. Xfigure_dropper (me, which)
  310. XNotify_client me;
  311. Xint which;
  312. X{
  313. X    /* if next position is unoccupied, move the figure down by 1 */
  314. X    if (safe_move (current_fig, current_rot, current_x, current_y+1))  {
  315. X    draw_figure (current_fig, current_rot, current_x*BLOCKSIZE+BOARD_X,
  316. X             current_y*BLOCKSIZE+BOARD_Y, BLACK);
  317. X    current_y++;
  318. X    draw_figure (current_fig, current_rot, current_x*BLOCKSIZE+BOARD_X,
  319. X             current_y*BLOCKSIZE+BOARD_Y, current_color);
  320. X    }
  321. X    else if (current_y < 0)  game_over ();    /* all over when at the top */
  322. X    else if (make_new_fig)  {
  323. X    make_new_fig = 0;
  324. X    place_figure ();    /* the figure comes to rest */
  325. X    new_figure ();        /* start a new one */
  326. X    }
  327. X    else  {
  328. X    make_new_fig = 1;
  329. X    }
  330. X}
  331. X
  332. X
  333. X/* drop_down drops the figure down as far as it can go without hitting
  334. X   other blocks along the way */
  335. Xstatic void
  336. Xdrop_down ()
  337. X{
  338. X    int new_y = current_y;
  339. X
  340. X    while (safe_move (current_fig, current_rot, current_x, new_y+1))  new_y++;
  341. X    if (new_y < 0)  {
  342. X    game_over ();
  343. X    return;
  344. X    }
  345. X    score += BOARDHEIGHT-(current_y+2);    /* bonus for dropping */
  346. X    draw_figure (current_fig, current_rot, current_x*BLOCKSIZE+BOARD_X,
  347. X         current_y*BLOCKSIZE+BOARD_Y, BLACK);
  348. X    current_y = new_y;
  349. X    draw_figure (current_fig, current_rot, current_x*BLOCKSIZE+BOARD_X,
  350. X         current_y*BLOCKSIZE+BOARD_Y, current_color);
  351. X    place_figure ();    /* rest the figure */
  352. X    new_figure ();    /* start a new one */
  353. X}
  354. X
  355. X
  356. Xstatic void
  357. Xgame_over ()
  358. X{
  359. X    stop_timer ();
  360. X    window_set (canvas, WIN_EVENT_PROC, wait_for_return, 0);
  361. X    close_board ();
  362. X    update_hs (score, level);
  363. X    display_hs ();
  364. X}
  365. X
  366. X
  367. X/* this select delay stuff doesn't work all that well, but it's sufficient */
  368. Xstatic struct timeval delay_1sec = { 0, 999999 };
  369. X
  370. X/* place the figure at its resting spot, update scores, do any reducing
  371. X   of rows */
  372. Xstatic void
  373. Xplace_figure ()
  374. X{
  375. X    stop_timer ();
  376. X    score += 2*level + BOARDHEIGHT-(current_y+2) + 5;
  377. X    mark_board (current_fig, current_rot, current_x, current_y);
  378. X    lines += reduce_rows (current_y);
  379. X    if (level < MAXLEVEL && lines > 10*(level+1))  {
  380. X    level++;    /* should pause for a sec */
  381. X    select (1, 0, 0, 0, &delay_1sec);
  382. X    }
  383. X    draw_score (lines, score, level);
  384. X    if (!paused)  start_timer ();
  385. X}
  386. X
  387. X
  388. X/* new_figure generates a new random figure */
  389. Xstatic void
  390. Xnew_figure ()
  391. X{
  392. X    current_x = 3;
  393. X    current_y = -1;
  394. X    current_rot = 0;
  395. X    current_fig = random () % 7;
  396. X    current_color = current_fig + 1;
  397. X    draw_figure (current_fig, current_rot, current_x*BLOCKSIZE+BOARD_X,
  398. X         current_y*BLOCKSIZE+BOARD_Y, current_color);
  399. X}
  400. X
  401. X
  402. X/*
  403. X * The cursor left (R10), 'j', and the left mouse button cause the block to
  404. X * move left.  R11, 'k', and the middle mouse button cause the block to
  405. X * rotate counter-clockwise.  The cursor right (R12), 'l', and the right
  406. X * mouse button cause the block to move right.  The cursor down (R14) and
  407. X * the spacebar cause the block to drop down to the bottom.
  408. X * The Cursor keys must not be emitting escape sequences (SunView Defaults)
  409. X */
  410. Xstatic void
  411. Xgame_control_proc (canvas, event)
  412. XCanvas canvas;
  413. XEvent *event;
  414. X{
  415. X    int new_x = current_x;
  416. X    int new_rot = current_rot;
  417. X
  418. X    if (event_is_button (event) && event_is_up (event))  return;
  419. X    switch (event_id (event))  {
  420. X    case 'q':
  421. X        exit (0);
  422. X    case MS_LEFT:
  423. X    case 'j':
  424. X    case KEY_RIGHT(10):    /* LEFT */
  425. X        new_x = current_x - 1;
  426. X        break;
  427. X    case MS_MIDDLE:
  428. X    case 'k':
  429. X    case KEY_RIGHT(11):    /* ROTATE */
  430. X        new_rot = (current_rot + 1) % 4;
  431. X        break;
  432. X    case MS_RIGHT:
  433. X    case 'l':
  434. X    case KEY_RIGHT(12):    /* RIGHT */
  435. X        new_x = current_x + 1;
  436. X        break;
  437. X    case ' ':
  438. X    case KEY_RIGHT(14):    /* DOWN */
  439. X        drop_down ();
  440. X        return;
  441. X        break;
  442. X    case 'u':
  443. X    case KEY_RIGHT(8):    /* UP LEVEL */
  444. X        if (level < MAXLEVEL)  {
  445. X        level++;
  446. X        stop_timer ();
  447. X        select (1, 0, 0, 0, &delay_1sec);
  448. X        draw_score (lines, score, level);
  449. X        start_timer ();
  450. X        }
  451. X        return;
  452. X        break;
  453. X    case LOC_WINENTER:
  454. X    case LOC_RGNENTER:
  455. X        start_timer ();
  456. X        paused = 0;
  457. X        return;
  458. X    case LOC_WINEXIT:
  459. X    case LOC_RGNEXIT:
  460. X        stop_timer ();
  461. X        paused = 1;
  462. X        return;
  463. X    default:
  464. X        return;
  465. X        break;
  466. X    }
  467. X    if (safe_move (current_fig, new_rot, new_x, current_y))  {
  468. X    draw_figure (current_fig, current_rot, current_x*BLOCKSIZE+BOARD_X,
  469. X             current_y*BLOCKSIZE+BOARD_Y, BLACK);
  470. X    current_rot = new_rot;
  471. X    current_x = new_x;
  472. X    draw_figure (current_fig, current_rot, current_x*BLOCKSIZE+BOARD_X,
  473. X             current_y*BLOCKSIZE+BOARD_Y, current_color);
  474. X    }
  475. X}
  476. X
  477. X
  478. X#define ITIMER_NULL ((struct itimerval *) 0)
  479. X
  480. Xstatic void
  481. Xstart_timer ()
  482. X{
  483. X    timer.it_interval.tv_usec = (11-level)*50000;
  484. X    timer.it_interval.tv_sec = 0;
  485. X    timer.it_value.tv_usec = (11-level)*50000;
  486. X    timer.it_value.tv_sec = 0;
  487. X    (void) notify_set_itimer_func (me, figure_dropper,
  488. X    ITIMER_REAL, &timer, ITIMER_NULL);
  489. X}
  490. X
  491. X
  492. Xstatic void
  493. Xstop_timer ()
  494. X{
  495. X    /* turn off timer */
  496. X    notify_set_itimer_func (me, figure_dropper, ITIMER_REAL, ITIMER_NULL,
  497. X    ITIMER_NULL);
  498. X}
  499. X
  500. X
  501. Xstatic void
  502. Xstart_game ()
  503. X{
  504. X    lines = 0;
  505. X    score = 0;
  506. X    make_new_fig = 0;
  507. X    draw_board ();
  508. X    draw_score (lines, score, level);
  509. X    rand_blocks (height);
  510. X    window_set (canvas, WIN_EVENT_PROC, game_control_proc, 0);
  511. X    new_figure ();
  512. X    start_timer ();
  513. X}
  514. X
  515. X
  516. Xstatic void
  517. Xchoose_level (canvas, event)
  518. XCanvas canvas;
  519. XEvent *event;
  520. X{
  521. X    switch (event_id (event))  {
  522. X    case '0':
  523. X    case '1':
  524. X    case '2':
  525. X    case '3':
  526. X    case '4':
  527. X    case '5':
  528. X    case '6':
  529. X    case '7':
  530. X    case '8':
  531. X    case '9':
  532. X        select_level (level);
  533. X        level = event_id (event) - '0';
  534. X        select_level (level);
  535. X        break;
  536. X    case 'q':
  537. X        exit (0);
  538. X    case 'h':
  539. X    case KEY_RIGHT(10):    /* LEFT */
  540. X        select_level (level);
  541. X        level = (level + 9) % 10;
  542. X        select_level (level);
  543. X        break;
  544. X    case 'l':
  545. X    case KEY_RIGHT(12):    /* RIGHT */
  546. X        select_level (level);
  547. X        level = (level + 1) % 10;
  548. X        select_level (level);
  549. X        break;
  550. X    case 'k':
  551. X    case KEY_RIGHT(8):    /* UP */
  552. X    case 'j':
  553. X    case KEY_RIGHT(14):    /* DOWN */
  554. X        select_level (level);
  555. X        level = (level + 5) % 10;
  556. X        select_level (level);
  557. X        break;
  558. X    case '\015':        /* RETURN */
  559. X        selht = 0;
  560. X        select_height (selht);
  561. X        window_set (canvas, WIN_EVENT_PROC, choose_height, 0);
  562. X        break;
  563. X    }
  564. X}
  565. X
  566. X
  567. Xstatic void
  568. Xchoose_height (canvas, event)
  569. XCanvas canvas;
  570. XEvent *event;
  571. X{
  572. X    switch (event_id (event))  {
  573. X    case 'q':
  574. X        exit (0);
  575. X    case 'h':
  576. X    case KEY_RIGHT(10):    /* LEFT */
  577. X        select_height (selht);
  578. X        selht = (selht + 5) % 6;
  579. X        select_height (selht);
  580. X        break;
  581. X    case 'l':
  582. X    case KEY_RIGHT(12):    /* RIGHT */
  583. X        select_height (selht);
  584. X        selht = (selht + 1) % 6;
  585. X        select_height (selht);
  586. X        break;
  587. X    case 'k':
  588. X    case KEY_RIGHT(8):    /* UP */
  589. X    case 'j':
  590. X    case KEY_RIGHT(14):    /* DOWN */
  591. X        select_height (selht);
  592. X        selht = (selht + 3) % 6;
  593. X        select_height (selht);
  594. X        break;
  595. X    case '\015':        /* RETURN */
  596. X        switch (selht)  {
  597. X        case 0: height = 0; break;
  598. X        case 1: height = 4; break;
  599. X        case 2: height = 7; break;
  600. X        case 3: height = 10; break;
  601. X        case 4: height = 13; break;
  602. X        }
  603. X        start_game ();
  604. X        break;
  605. X    }
  606. X}
  607. X
  608. X
  609. Xstatic void
  610. Xwait_for_return (canvas, event)
  611. XCanvas canvas;
  612. XEvent *event;
  613. X{
  614. X    switch (event_id (event))  {
  615. X    case 'q':  exit (0);
  616. X    case '\015':
  617. X        game_setup ();
  618. X        break;
  619. X    }
  620. X}
  621. X
  622. X        
  623. Xstatic void
  624. Xgame_setup ()
  625. X{
  626. X    display_choices ();
  627. X    window_set (canvas, WIN_EVENT_PROC, choose_level, 0);
  628. X    level = 5;
  629. X    select_level (level);
  630. X}
  631. END_OF_FILE
  632. if test 9581 -ne `wc -c <'suntetris.c'`; then
  633.     echo shar: \"'suntetris.c'\" unpacked with wrong size!
  634. fi
  635. # end of 'suntetris.c'
  636. fi
  637. if test -f 'suntetris.h' -a "${1}" != "-c" ; then 
  638.   echo shar: Will not clobber existing file \"'suntetris.h'\"
  639. else
  640. echo shar: Extracting \"'suntetris.h'\" \(1088 characters\)
  641. sed "s/^X//" >'suntetris.h' <<'END_OF_FILE'
  642. X/* @(#)suntetris.h    1.9 3/22/89 */
  643. X/*
  644. X *  Copyright 1989, Rick Iwamoto iwamoto@sun.com
  645. X *  Permission is given to copy and distribute for non-profit purposes. 
  646. X */
  647. X
  648. X#define MAXLEVEL 9
  649. X#define BOARDWIDTH 10
  650. X#define BOARDHEIGHT 20
  651. X#define BOARD_X 200
  652. X#define BOARD_Y 50
  653. X#define BLOCKSIZE 16
  654. X#define SCREENDEPTH 8
  655. X#define SCORE_Y BOARD_Y+50
  656. X#define LINES_Y BOARD_Y+100
  657. X#define LEVEL_Y BOARD_Y+150
  658. X#define TETRISCMSSIZE 16
  659. X
  660. X#define    BLACK    0
  661. X#define    RED    1
  662. X#define    YELLOW    2
  663. X#define    LTGREEN    3
  664. X#define    GREEN    4
  665. X#define    BLUE    5
  666. X#define    VIOLET    6
  667. X#define    CYAN    7
  668. X#define    WHITE    15
  669. X
  670. X#define    tetris_cms(r,g,b) \
  671. X    (r)[BLACK] = 0;        (g)[BLACK] = 0;        (b)[BLACK] = 0; \
  672. X    (r)[RED] = 255;        (g)[RED] = 0;        (b)[RED] = 0; \
  673. X    (r)[YELLOW] = 255;    (g)[YELLOW] = 255;    (b)[YELLOW] = 0; \
  674. X    (r)[LTGREEN] = 180;    (g)[LTGREEN] = 255;    (b)[LTGREEN] = 180; \
  675. X    (r)[GREEN] = 0;        (g)[GREEN] = 255;    (b)[GREEN] = 0; \
  676. X    (r)[BLUE] = 0;        (g)[BLUE] = 0;        (b)[BLUE] = 255; \
  677. X    (r)[VIOLET] = 255;    (g)[VIOLET] = 0;    (b)[VIOLET] = 255; \
  678. X    (r)[CYAN] = 0;        (g)[CYAN] = 255;    (b)[CYAN] = 255; \
  679. X    (r)[WHITE] = 255;    (g)[WHITE] = 255;    (b)[WHITE] = 255;
  680. END_OF_FILE
  681. if test 1088 -ne `wc -c <'suntetris.h'`; then
  682.     echo shar: \"'suntetris.h'\" unpacked with wrong size!
  683. fi
  684. # end of 'suntetris.h'
  685. fi
  686. if test -f 'suntetris.icon' -a "${1}" != "-c" ; then 
  687.   echo shar: Will not clobber existing file \"'suntetris.icon'\"
  688. else
  689. echo shar: Extracting \"'suntetris.icon'\" \(1933 characters\)
  690. sed "s/^X//" >'suntetris.icon' <<'END_OF_FILE'
  691. X/* Format_version=1, Width=64, Height=64, Depth=1, Valid_bits_per_item=16
  692. X */
  693. X    0xFFFF,0xFFFF,0xFFFF,0xFFFF,0x8000,0x0000,0x0000,0x0001,
  694. X    0xBFFF,0xFFFF,0xFFFF,0xFFFD,0xBFFF,0xFFFF,0xFFFF,0xFFFD,
  695. X    0xBFFF,0xFFFF,0xFFFF,0xFFFD,0xBF81,0xFFFF,0xFFFF,0xFFFD,
  696. X    0xBFA5,0xFFFF,0xFFFF,0xFFFD,0xBFE7,0xFFFF,0xFFFF,0xFFFD,
  697. X    0xBFE7,0xFFFF,0xFFFF,0xFFFD,0xBFE7,0xFFFF,0xFFFF,0xFFFD,
  698. X    0xBFC3,0xFFFF,0xFFFF,0xFFFD,0xBFFF,0xFFFF,0xFFFF,0xFFFD,
  699. X    0xBFFF,0xFFFF,0xFFF0,0xFFFD,0xBF81,0xFFFF,0xFFF0,0xFFFD,
  700. X    0xBFDD,0xFFFF,0xFFF0,0xFFFD,0xBFC7,0xFFFF,0xFFF0,0xFFFD,
  701. X    0xBFDF,0xFFFF,0xFF00,0xFFFD,0xBFDD,0xFFFF,0xFF00,0xFFFD,
  702. X    0xBF81,0xFFFF,0xFF00,0xFFFD,0xBFFF,0xFFFF,0xFF00,0xFFFD,
  703. X    0xBFFF,0xFFFF,0xFF0F,0xFFFD,0xBF81,0xFFFF,0xFF0F,0xFFFD,
  704. X    0xBFA5,0xFFFF,0xFF0F,0xFFFD,0xBFE7,0xFFFF,0xFF0F,0xFFFD,
  705. X    0xBFE7,0xFFFF,0xFFFF,0xFFFD,0xBFE7,0xFFFF,0xFFFF,0xFFFD,
  706. X    0xBFC3,0xFFFF,0xFFFF,0xFFFD,0xBFFF,0xFFFF,0xFFFF,0xFFFD,
  707. X    0xBFFF,0xFFFF,0xFFFF,0xFFFD,0xBF83,0xFFFF,0xFFFF,0xFFFD,
  708. X    0xBFD9,0xFFFF,0xFFFF,0xFFFD,0xBFD9,0xFFFF,0xFFFF,0xFFFD,
  709. X    0xBFC3,0xFFFF,0xFFFF,0xFFFD,0xBFDB,0xFFFF,0xFFFF,0xFFFD,
  710. X    0xBF99,0xFFFF,0xFFFF,0xFFFD,0xBFFF,0xFFFF,0xFFFF,0xFFFD,
  711. X    0xBFFF,0xFFFF,0xFFFF,0xFF8D,0xBFC3,0xFFFF,0xFFFF,0xFF8D,
  712. X    0xBFE7,0xFFFF,0xFFFF,0xFF2D,0xBFE7,0xFFFF,0xFFFF,0xFF2D,
  713. X    0xBFE7,0xFFFF,0xFFFF,0xFF8D,0xBFE7,0xFFFF,0xFFFF,0xFF8D,
  714. X    0xBFC3,0xFFFF,0xFFFF,0xFF2D,0xBFFF,0xFFFF,0xFFFF,0xFF2D,
  715. X    0xBFFF,0xFF87,0x7FFF,0xFF8D,0xBFC1,0xFF8D,0xDFFF,0xFF8D,
  716. X    0xBF9D,0xFF2B,0xBFFF,0xFF2D,0xBF87,0xFF2E,0xEFFF,0xFF2D,
  717. X    0xBFE1,0xF88A,0x77FF,0xAF8D,0xBFB9,0xF885,0xDDFF,0x5F8D,
  718. X    0xBF83,0xF22A,0xBBFF,0xAF2D,0xBFFF,0xF225,0xEEFF,0x5F2D,
  719. X    0xBFFF,0xF08A,0xAAFF,0xA88D,0xBFFF,0xF085,0x55FF,0x522D,
  720. X    0xBFFF,0xF02A,0xAAFF,0xA44D,0xBFFF,0xF025,0x55FF,0x511D,
  721. X    0xBFFF,0xF088,0x88FA,0xA88D,0xBFFF,0xF022,0x22F5,0x522D,
  722. X    0xBFFF,0xF044,0x44FA,0xA44D,0xBFFF,0xF011,0x11F5,0x511D,
  723. X    0xBFFF,0xFFFF,0xFFFF,0xFFFD,0xBFFF,0xFFFF,0xFFFF,0xFFFD,
  724. X    0x8000,0x0000,0x0000,0x0001,0xFFFF,0xFFFF,0xFFFF,0xFFFF
  725. END_OF_FILE
  726. if test 1933 -ne `wc -c <'suntetris.icon'`; then
  727.     echo shar: \"'suntetris.icon'\" unpacked with wrong size!
  728. fi
  729. # end of 'suntetris.icon'
  730. fi
  731. if test -f 'suntetris_pw.c' -a "${1}" != "-c" ; then 
  732.   echo shar: Will not clobber existing file \"'suntetris_pw.c'\"
  733. else
  734. echo shar: Extracting \"'suntetris_pw.c'\" \(15955 characters\)
  735. sed "s/^X//" >'suntetris_pw.c' <<'END_OF_FILE'
  736. X#ifndef lint
  737. Xstatic char sccsid[] = "@(#)suntetris_pw.c    1.14 3/23/89";
  738. X#endif
  739. X/*
  740. X *  Copyright 1989, Rick Iwamoto iwamoto@sun.com
  741. X *  Permission is given to copy and distribute for non-profit purposes. 
  742. X */
  743. X
  744. X#include <stdio.h>
  745. X#include <suntool/sunview.h>
  746. X#include <suntool/canvas.h>
  747. X#include "suntetris.h"
  748. X#include <pwd.h>
  749. X#include <unistd.h>
  750. X
  751. Xextern Canvas canvas;
  752. Xstatic Pixwin *pw;
  753. Xstatic Pixfont *bigfont;
  754. Xstatic Pixrect *savepr;
  755. Xstatic int incolor;
  756. Xstatic int boardmap[BOARDWIDTH][BOARDHEIGHT];
  757. X
  758. Xtypedef
  759. Xstruct figure  {
  760. X    int x[4], y[4];
  761. X} Figure;
  762. X
  763. Xstatic Figure fig1a = { { 2, 1, 0, 0 }, { 2, 2, 2, 1 } };
  764. Xstatic Figure fig1b = { { 1, 1, 1, 0 }, { 0, 1, 2, 2 } };
  765. Xstatic Figure fig1c = { { 0, 1, 2, 2 }, { 1, 1, 1, 2 } };
  766. Xstatic Figure fig1d = { { 1, 1, 1, 2 }, { 2, 1, 0, 0 } };
  767. Xstatic Figure fig2a = { { 0, 1, 2, 2 }, { 2, 2, 2, 1 } };
  768. Xstatic Figure fig2b = { { 1, 1, 1, 0 }, { 2, 1, 0, 0 } };
  769. Xstatic Figure fig2c = { { 2, 1, 0, 0 }, { 1, 1, 1, 2 } };
  770. Xstatic Figure fig2d = { { 1, 1, 1, 2 }, { 0, 1, 2, 2 } };
  771. Xstatic Figure fig3a = { { 0, 1, 2, 1 }, { 2, 2, 2, 1 } };
  772. Xstatic Figure fig3b = { { 1, 1, 1, 0 }, { 2, 1, 0, 1 } };
  773. Xstatic Figure fig3c = { { 2, 1, 0, 1 }, { 1, 1, 1, 2 } };
  774. Xstatic Figure fig3d = { { 1, 1, 1, 2 }, { 0, 1, 2, 1 } };
  775. Xstatic Figure fig4a = { { 0, 1, 1, 2 }, { 1, 1, 2, 2 } };
  776. Xstatic Figure fig4b = { { 1, 1, 2, 2 }, { 2, 1, 1, 0 } };
  777. Xstatic Figure fig5a = { { 0, 1, 1, 2 }, { 2, 2, 1, 1 } };
  778. Xstatic Figure fig5b = { { 2, 2, 1, 1 }, { 2, 1, 1, 0 } };
  779. Xstatic Figure fig6a = { { 0, 1, 2, 3 }, { 1, 1, 1, 1 } };
  780. Xstatic Figure fig6b = { { 2, 2, 2, 2 }, { 3, 2, 1, 0 } };
  781. Xstatic Figure fig7 = { { 0, 1, 0, 1 }, { 1, 1, 2, 2 } };
  782. X
  783. X
  784. Xstatic Figure *figures[7][4] = {
  785. X    { &fig1a, &fig1b, &fig1c, &fig1d },    /* backward L */
  786. X    { &fig2a, &fig2b, &fig2c, &fig2d },    /* L */
  787. X    { &fig3a, &fig3b, &fig3c, &fig3d },    /* T */
  788. X    { &fig4a, &fig4b, &fig4a, &fig4b },    /* Z */
  789. X    { &fig5a, &fig5b, &fig5a, &fig5b },    /* S */
  790. X    { &fig6a, &fig6b, &fig6a, &fig6b },    /* I */
  791. X    { &fig7, &fig7, &fig7, &fig7 }    /* Square block */
  792. X};
  793. X
  794. X
  795. Xstatic bordercolor[8] =
  796. X    { BLACK, GREEN, LTGREEN, VIOLET, RED, BLUE, YELLOW, CYAN };
  797. Xstatic fillcolor[8] =
  798. X    { BLACK, RED, GREEN, RED, BLACK, VIOLET, RED, WHITE };
  799. X
  800. Xstatic short bwdata0[] = {    /* BLACK */
  801. X    0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,
  802. X    0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF
  803. X};
  804. Xmpr_static (bwblock0, BLOCKSIZE, BLOCKSIZE, 1, bwdata0);
  805. Xstatic short bwdata1[] = {    /* root middle */
  806. X    0x0000,0x0000,0x2220,0x2220,0x0888,0x0888,0x2220,0x2220,
  807. X    0x0888,0x0888,0x2220,0x2220,0x0888,0x0888,0x0000,0x0000
  808. X};
  809. Xmpr_static (bwblock1, BLOCKSIZE, BLOCKSIZE, 1, bwdata1);
  810. Xstatic short bwdata2[] = {    /* 25 % middle */
  811. X    0x0000,0x0000,0x0444,0x1110,0x0888,0x2220,0x0444,0x1110,
  812. X    0x0888,0x2220,0x0444,0x1110,0x0888,0x2220,0x0000,0x0000
  813. X};
  814. Xmpr_static (bwblock2, BLOCKSIZE, BLOCKSIZE, 1, bwdata2);
  815. Xstatic short bwdata3[] = {    /* 50 % middle */
  816. X    0x0000,0x0000,0x2AA8,0x1554,0x2AA8,0x1554,0x2AA8,0x1554,
  817. X    0x2AA8,0x1554,0x2AA8,0x1554,0x2AA8,0x1554,0x0000,0x0000
  818. X};
  819. Xmpr_static (bwblock3, BLOCKSIZE, BLOCKSIZE, 1, bwdata3);
  820. Xstatic short bwdata4[] = {    /* 75 % middle */
  821. X    0x0000,0x0000,0x3BB8,0x2EEC,0x3774,0x1DDC,0x3BB8,0x2EEC,
  822. X    0x3774,0x1DDC,0x3BB8,0x2EEC,0x3774,0x1DDC,0x0000,0x0000
  823. X};
  824. Xmpr_static (bwblock4, BLOCKSIZE, BLOCKSIZE, 1, bwdata4);
  825. Xstatic short bwdata5[] = {    /* horiz middle */
  826. X    0x0000,0x0000,0x3FFC,0x0000,0x3FFC,0x0000,0x3FFC,0x0000,
  827. X    0x3FFC,0x0000,0x3FFC,0x0000,0x3FFC,0x0000,0x0000,0x0000
  828. X};
  829. Xmpr_static (bwblock5, BLOCKSIZE, BLOCKSIZE, 1, bwdata5);
  830. Xstatic short bwdata6[] = {    /* diag middle */
  831. X    0x0000,0x0000,0x2490,0x1248,0x0924,0x2490,0x1248,0x0924,
  832. X    0x2490,0x1248,0x0924,0x2490,0x1248,0x0924,0x0000,0x0000
  833. X};
  834. Xmpr_static (bwblock6, BLOCKSIZE, BLOCKSIZE, 1, bwdata6);
  835. Xstatic short bwdata7[] = {    /* checker middle */
  836. X    0x0000,0x0000,0x3330,0x3330,0x0CCC,0x0CCC,0x3330,0x3330,
  837. X    0x0CCC,0x0CCC,0x3330,0x3330,0x0CCC,0x0CCC,0x0000,0x0000
  838. X};
  839. Xmpr_static (bwblock7, BLOCKSIZE, BLOCKSIZE, 1, bwdata7);
  840. Xstatic Pixrect *bwblocks[8] = {
  841. X    &bwblock0, &bwblock1, &bwblock2, &bwblock3, 
  842. X    &bwblock4, &bwblock5, &bwblock6, &bwblock7
  843. X};
  844. X
  845. X#define BORDER 2
  846. X
  847. X/* draw_block draws a single block according to color or black&white mode */
  848. X#define draw_block(x,y,color) { \
  849. X    if (incolor)  { \
  850. X    pw_rop (pw, (x), (y), BLOCKSIZE, BLOCKSIZE, \
  851. X        PIX_SRC | PIX_COLOR(bordercolor[color]), 0, 0, 0); \
  852. X    pw_rop (pw, (x)+BORDER, (y)+BORDER, \
  853. X        BLOCKSIZE-2*BORDER, BLOCKSIZE-2*BORDER, \
  854. X        PIX_SRC | PIX_COLOR(fillcolor[color]), 0, 0, 0); \
  855. X    } else \
  856. X    pw_rop (pw, (x), (y), BLOCKSIZE, BLOCKSIZE, \
  857. X        PIX_NOT(PIX_SRC), bwblocks[color], 0, 0); \
  858. X    }
  859. X    
  860. X
  861. X/* draw_figure draws one of the 7 figures in the specified orientation
  862. X   at the location on the canvas */
  863. Xvoid
  864. Xdraw_figure (figno, orientation, pix_x, pix_y, color)
  865. Xint figno, orientation, pix_x, pix_y, color;
  866. X{
  867. X    int i;
  868. X
  869. X    if (figno > 6 || orientation > 3)  exit (1);
  870. X    pw_batch_on (pw);
  871. X    for (i = 0; i < 4; i++)
  872. X    draw_block (pix_x+(figures[figno][orientation]->x[i])*BLOCKSIZE,
  873. X        pix_y+(figures[figno][orientation]->y[i])*BLOCKSIZE, color)
  874. X    pw_batch_off (pw);
  875. X}
  876. X
  877. X
  878. X/* safe_move tells when the block will collide with another or when it
  879. X   is at the border of the board */
  880. Xsafe_move (figno, orientation, x, y)
  881. Xint figno, orientation, x, y;
  882. X{
  883. X    int i, xpos, ypos;
  884. X
  885. X    for (i = 0; i < 4; i++)  {
  886. X    xpos = x+figures[figno][orientation]->x[i];
  887. X    ypos = y+figures[figno][orientation]->y[i];
  888. X    if (xpos < 0 || xpos >= BOARDWIDTH || ypos < 0 || ypos >= BOARDHEIGHT
  889. X        || boardmap[xpos][ypos] != 0)  return (0);
  890. X    }
  891. X    return (1);
  892. X}
  893. X
  894. X
  895. X/* mark_board logs the specified figure on the boardmap, which keeps track
  896. X   of all pieces which have come to rest */
  897. Xvoid
  898. Xmark_board (figno, orientation, x, y)
  899. Xint figno, orientation, x, y;
  900. X{
  901. X    int i, xpos, ypos;
  902. X
  903. X    for (i = 0; i < 4; i++)  {
  904. X    xpos = x+figures[figno][orientation]->x[i];
  905. X    ypos = y+figures[figno][orientation]->y[i];
  906. X    boardmap[xpos][ypos] = 1;
  907. X    }
  908. X}
  909. X
  910. X
  911. Xstatic struct timeval delay_50ms = { 0, 50000 };
  912. X
  913. X/* reduce_rows checks for solid blocks across rows on the board,
  914. X   flashes the rows to be deleted, then deletes them from the board
  915. X   as well as the boardmap */
  916. Xreduce_rows (y)
  917. Xint y;
  918. X{
  919. X    int i, j, skip = 0, reducing = 0;
  920. X    static int reduce[BOARDHEIGHT] = {
  921. X        0, 0, 0, 0, 0,
  922. X        0, 0, 0, 0, 0,
  923. X        0, 0, 0, 0, 0,
  924. X        0, 0, 0, 0, 0 };
  925. X
  926. X    /* check for solid rows */
  927. X    /* log all of the rows which need to be deleted into reduce[] */
  928. X    /* At most 4 rows can be deleted at one time */
  929. X    for (j = y+3; j >= y; j--)  {
  930. X    if (j >= BOARDHEIGHT)  continue;
  931. X        /* for some blocks j can be past bottom */
  932. X    reduce[j] = 1;
  933. X    for (i = 0; i < BOARDWIDTH && reduce[j]; i++)
  934. X        reduce[j] &= boardmap[i][j];
  935. X    reducing |= reduce[j];
  936. X    if (reduce[j])    /* save any rows-to-be-reduced for flashing */
  937. X        pw_read (savepr, 0, (j-y)*BLOCKSIZE, BOARDWIDTH*BLOCKSIZE,
  938. X        BLOCKSIZE, PIX_SRC, pw, BOARD_X, BOARD_Y+j*BLOCKSIZE);
  939. X    }
  940. X    if (!reducing)  return (0);
  941. X    select (1, 0, 0, 0, &delay_50ms);
  942. X    for (i = 0; i < 3; i++)  {    /* flash rows 3 times */
  943. X    for (j = y+3; j >= y; j--)  {
  944. X        if (j < BOARDHEIGHT && reduce[j])    /* erase rows */
  945. X        pw_writebackground (pw, BOARD_X, BOARD_Y+j*BLOCKSIZE,
  946. X            BOARDWIDTH*BLOCKSIZE, BLOCKSIZE, PIX_CLR);
  947. X    }
  948. X    select (1, 0, 0, 0, &delay_50ms);
  949. X    for (j = y+3; j >= y; j--)  {
  950. X        if (j < BOARDHEIGHT && reduce[j])    /* restore rows */
  951. X        pw_rop (pw, BOARD_X, BOARD_Y+j*BLOCKSIZE, BOARDWIDTH*BLOCKSIZE,
  952. X            BLOCKSIZE, PIX_SRC, savepr, 0, (j-y)*BLOCKSIZE);
  953. X    }
  954. X    select (1, 0, 0, 0, &delay_50ms);
  955. X    }
  956. X    pw_batch_on (pw);
  957. X    /*  next, starting from the bottom of the board,
  958. X    we do nothing if the row is to be deleted,
  959. X    we copy the non-full row down by how many have been deleted
  960. X    under it */
  961. X    for (j = y+3; j >= 0; j--)  {    /* remove rows */
  962. X    if (j >= BOARDHEIGHT)  continue;
  963. X    if (reduce[j])  {
  964. X        skip++;
  965. X        reduce[j] = 0;
  966. X    }
  967. X    else if (skip > 0)  {
  968. X        for (i = 0; i < BOARDWIDTH; i++)
  969. X        boardmap[i][j+skip] = boardmap[i][j];
  970. X        pw_copy (pw, BOARD_X, BOARD_Y+(j+skip)*BLOCKSIZE,
  971. X        BLOCKSIZE*BOARDWIDTH, BLOCKSIZE,        /* one row */
  972. X        PIX_SRC, pw, BOARD_X, BOARD_Y+j*BLOCKSIZE);
  973. X    }
  974. X    }
  975. X    /* shift remaining blocks down by number of deleted rows */
  976. X    pw_writebackground (pw, BOARD_X, BOARD_Y, BLOCKSIZE*BOARDWIDTH,
  977. X    BLOCKSIZE*skip, PIX_CLR);
  978. X    pw_batch_off (pw);
  979. X    return (skip);
  980. X}
  981. X
  982. X#define BORDER_PIXOP (PIX_SRC | PIX_COLOR(RED))
  983. X#define TEXT_PIXOP (PIX_SRC | PIX_COLOR(YELLOW))
  984. X
  985. X/* close_board does the closing door effect when the game is over */
  986. Xvoid
  987. Xclose_board ()
  988. X{
  989. X    int i, j;
  990. X    static struct timeval delay_100ms = { 0, 100000 };
  991. X
  992. X    for (i = 0; i < BOARDHEIGHT; i++)        /* clear boardmap */
  993. X    for (j = 0; j < BOARDWIDTH; j++)  boardmap[j][i] = 0;
  994. X    select (1, 0, 0, 0, &delay_100ms);
  995. X    for (i = 0; i < BOARDHEIGHT/2; i++)  {
  996. X    pw_batch_on (pw);
  997. X    for (j = 0; j < BOARDWIDTH; j++)  {
  998. X        draw_block (BOARD_X+j*BLOCKSIZE, BOARD_Y+i*BLOCKSIZE, 2)
  999. X        draw_block (BOARD_X+j*BLOCKSIZE,
  1000. X        BOARD_Y+(BOARDHEIGHT-1-i)*BLOCKSIZE, 2);
  1001. X    }
  1002. X    pw_batch_off (pw);
  1003. X    select (1, 0, 0, 0, &delay_100ms);
  1004. X    }
  1005. X    pw_text (pw, BOARD_X+2*BLOCKSIZE, BOARD_Y+BLOCKSIZE*BOARDHEIGHT/2,
  1006. X    TEXT_PIXOP, bigfont, "GAME OVER");
  1007. X    select (1, 0, 0, 0, &delay_100ms);
  1008. X}
  1009. X
  1010. X
  1011. Xvoid draw_score (lines, score, level)
  1012. Xint lines, score, level;
  1013. X{
  1014. X    char s[10];
  1015. X
  1016. X    pw_batch_on (pw);
  1017. X    sprintf (s, "%6d", lines);
  1018. X    pw_text (pw, 100, LINES_Y, TEXT_PIXOP, bigfont, s);
  1019. X    sprintf (s, "%6d", score);
  1020. X    pw_text (pw, 100, SCORE_Y, TEXT_PIXOP, bigfont, s);
  1021. X    sprintf (s, "%6d", level);
  1022. X    pw_text (pw, 100, LEVEL_Y, TEXT_PIXOP, bigfont, s);
  1023. X    pw_batch_off (pw);
  1024. X}
  1025. X
  1026. X
  1027. Xvoid
  1028. Xdraw_board ()
  1029. X{
  1030. X    pw_batch_on (pw);
  1031. X    pw_writebackground (pw, 0, 0, pw->pw_pixrect->pr_width,
  1032. X    pw->pw_pixrect->pr_height, PIX_CLR);    /* clear screen */
  1033. X    pw_writebackground (pw, BOARD_X-4, BOARD_Y-4, 2, BOARDHEIGHT*BLOCKSIZE+8,
  1034. X    BORDER_PIXOP);
  1035. X    pw_writebackground (pw, BOARD_X-4, BOARD_Y-4, BOARDWIDTH*BLOCKSIZE+8, 2,
  1036. X    BORDER_PIXOP);
  1037. X    pw_writebackground (pw, BOARD_X+BOARDWIDTH*BLOCKSIZE+2, BOARD_Y-4,
  1038. X    2, BOARDHEIGHT*BLOCKSIZE+8, BORDER_PIXOP);
  1039. X    pw_writebackground (pw, BOARD_X-4, BOARD_Y+BOARDHEIGHT*BLOCKSIZE+2,
  1040. X    BOARDWIDTH*BLOCKSIZE+8, 2, BORDER_PIXOP);
  1041. X    pw_ttext (pw, 20, SCORE_Y, TEXT_PIXOP, bigfont, "SCORE");
  1042. X    pw_ttext (pw, 20, LINES_Y, TEXT_PIXOP, bigfont, "LINES");
  1043. X    pw_ttext (pw, 20, LEVEL_Y, TEXT_PIXOP, bigfont, "LEVEL");
  1044. X    pw_batch_off (pw);
  1045. X}
  1046. X
  1047. X
  1048. X/* init_pw gets the pixwin from the canvas and sets up the colormap */
  1049. Xvoid
  1050. Xinit_pw (forcebw)
  1051. Xint forcebw;
  1052. X{
  1053. X    u_char red[TETRISCMSSIZE], green[TETRISCMSSIZE], blue[TETRISCMSSIZE];
  1054. X
  1055. X    bigfont = pf_open ("/usr/lib/fonts/fixedwidthfonts/gallant.r.19");
  1056. X    pw = (Pixwin *) window_get (canvas, WIN_PIXWIN);
  1057. X    incolor = (pw->pw_pixrect->pr_depth == 8);
  1058. X    if (forcebw)  incolor = 0;
  1059. X    tetris_cms(red, green, blue)
  1060. X    pw_setcmsname (pw, "suntetris");
  1061. X    pw_putcolormap (pw, 0, TETRISCMSSIZE, red, green, blue);
  1062. X    pw = canvas_pixwin (canvas);
  1063. X    pw_setcmsname (pw, "suntetris");
  1064. X    pw_putcolormap (pw, 0, TETRISCMSSIZE, red, green, blue);
  1065. X    savepr = mem_create (BOARDWIDTH*BLOCKSIZE, 4*BLOCKSIZE,
  1066. X         incolor?8:1);
  1067. X}
  1068. X
  1069. X
  1070. X/* rand_blocks draws a random assortment of blocks to the specified height
  1071. X   on the board and logs them into the boardmap */
  1072. Xvoid
  1073. Xrand_blocks (height)
  1074. Xint height;
  1075. X{
  1076. X    int x, y, r;
  1077. X
  1078. X    pw_batch_on (pw);
  1079. X    for (y = BOARDHEIGHT-height; y < BOARDHEIGHT; y++)  {
  1080. X    for (x = 0; x < BOARDWIDTH; x ++)  {
  1081. X        r = random ();
  1082. X        if (r % 4 == 0)  {
  1083. X        boardmap[x][y] = 1;
  1084. X        draw_block (BOARD_X+x*BLOCKSIZE,
  1085. X            BOARD_Y+y*BLOCKSIZE, (r/4) % 7 + 1)
  1086. X        }
  1087. X    }
  1088. X    }
  1089. X    pw_batch_off (pw);
  1090. X}
  1091. X
  1092. X
  1093. X#define BOXSIZE 32
  1094. X#define CHOICE_PIXOP PIX_NOT(PIX_SRC)
  1095. X#define CADJX 10
  1096. X#define CADJY BOXSIZE-8
  1097. X#define LVX 50
  1098. X#define HTX 260
  1099. X#define LVY BOARD_Y+10
  1100. X#define HTY BOARD_Y+10
  1101. X
  1102. X/* display_choices draws the level selection and height selection boxes */
  1103. Xvoid
  1104. Xdisplay_choices ()
  1105. X{
  1106. X    int i;
  1107. X
  1108. X    pw_batch_on (pw);
  1109. X    pw_writebackground (pw, 0, 0, pw->pw_pixrect->pr_width,
  1110. X    pw->pw_pixrect->pr_height, PIX_CLR);    /* clear screen */
  1111. X    pw_text (pw, LVX, BOARD_Y, PIX_SRC, bigfont, "LEVEL");
  1112. X    pw_text (pw, HTX, BOARD_Y, PIX_SRC, bigfont, "HEIGHT");
  1113. X    for (i = 0; i < 6; i++)
  1114. X    pw_writebackground (pw, LVX+i*BOXSIZE, LVY, 2, 2*BOXSIZE, PIX_SET);
  1115. X    for (i = 0; i < 4; i++)
  1116. X    pw_writebackground (pw, HTX+i*BOXSIZE, HTY, 2, 2*BOXSIZE, PIX_SET);
  1117. X    for (i = 0; i < 3; i++)  {
  1118. X    pw_writebackground (pw, LVX, LVY+i*BOXSIZE, 5*BOXSIZE+2, 2,
  1119. X        PIX_SET);
  1120. X    pw_writebackground (pw, HTX, HTY+i*BOXSIZE, 3*BOXSIZE+2, 2,
  1121. X        PIX_SET);
  1122. X    }
  1123. X    for (i = 0; i <= 9; i++)
  1124. X    pw_char (pw, LVX+(i%5)*32+CADJX, LVY+(i/5)*32+CADJY, PIX_SRC,
  1125. X        bigfont, i+'0');
  1126. X    pw_char (pw, HTX+CADJX, HTY+CADJY, PIX_SRC, bigfont, '0');
  1127. X    pw_char (pw, HTX+BOXSIZE+CADJX, HTY+CADJY, PIX_SRC, bigfont, '4');
  1128. X    pw_char (pw, HTX+2*BOXSIZE+CADJX, HTY+CADJY, PIX_SRC, bigfont, '7');
  1129. X    pw_text (pw, HTX-6+CADJX, HTY+BOXSIZE+CADJY, PIX_SRC, bigfont, "10");
  1130. X    pw_text (pw, HTX-6+BOXSIZE+CADJX, HTY+BOXSIZE+CADJY, PIX_SRC, bigfont,
  1131. X    "13");
  1132. X    pw_text (pw, HTX-6+2*BOXSIZE+CADJX, HTY+BOXSIZE+CADJY, PIX_SRC, bigfont,
  1133. X    ">>");
  1134. X    pw_batch_off (pw);
  1135. X}
  1136. X
  1137. X
  1138. X/* select_level inverts the box corresponding to the specified level */
  1139. Xvoid
  1140. Xselect_level (level)
  1141. Xint level;
  1142. X{
  1143. X    pw_copy (pw, LVX+(level%5)*BOXSIZE+2, LVY+(level/5)*BOXSIZE+2,
  1144. X    BOXSIZE-2, BOXSIZE-2, PIX_NOT(PIX_SRC),
  1145. X    pw, LVX+(level%5)*BOXSIZE+2, LVY+(level/5)*BOXSIZE+2);
  1146. X}
  1147. X
  1148. X
  1149. X/* select_height inverts the box corresponding to the specified height
  1150. X   position onscreen (0-5) not the actual height (0,4,7,10,13,>>) */
  1151. Xvoid
  1152. Xselect_height (height)
  1153. Xint height;
  1154. X{
  1155. X    pw_copy (pw, HTX+(height%3)*BOXSIZE+2, HTY+(height/3)*BOXSIZE+2,
  1156. X    BOXSIZE-2, BOXSIZE-2, PIX_NOT(PIX_SRC),
  1157. X    pw, HTX+(height%3)*BOXSIZE+2, HTY+(height/3)*BOXSIZE+2);
  1158. X}
  1159. X
  1160. X
  1161. Xstatic struct highscores  {
  1162. X    char name[16];
  1163. X    int level, score;
  1164. X} highs[10] =  {
  1165. X    "nobody", 0, 0,
  1166. X    "nobody", 0, 0,
  1167. X    "nobody", 0, 0,
  1168. X    "nobody", 0, 0,
  1169. X    "nobody", 0, 0,
  1170. X    "nobody", 0, 0,
  1171. X    "nobody", 0, 0,
  1172. X    "nobody", 0, 0,
  1173. X    "nobody", 0, 0,
  1174. X    "nobody", 0, 0,
  1175. X};
  1176. X
  1177. X#define SPACING 32
  1178. X#define HIGHS_X 30
  1179. X#define HIGHS_Y 80
  1180. X
  1181. Xvoid
  1182. Xdisplay_hs ()
  1183. X{
  1184. X    int i;
  1185. X    char s[8];
  1186. X
  1187. X    pw_batch_on (pw);
  1188. X    pw_writebackground (pw, 0, 0, pw->pw_pixrect->pr_width,
  1189. X    pw->pw_pixrect->pr_height, PIX_CLR);    /* clear screen */
  1190. X    pw_text (pw, HIGHS_X, HIGHS_Y-SPACING, PIX_SRC, bigfont, "NAME");
  1191. X    pw_text (pw, HIGHS_X+160, HIGHS_Y-SPACING, PIX_SRC, bigfont, "LEVEL");
  1192. X    pw_text (pw, HIGHS_X+270, HIGHS_Y-SPACING, PIX_SRC, bigfont, "SCORE");
  1193. X    for (i = 0; i < 10; i++)  {
  1194. X    pw_text (pw, HIGHS_X, HIGHS_Y+i*SPACING, PIX_SRC, bigfont,
  1195. X        highs[i].name);
  1196. X    pw_char (pw, HIGHS_X+180, HIGHS_Y+i*SPACING, PIX_SRC, bigfont,
  1197. X        highs[i].level+'0');
  1198. X    sprintf (s, "%5d", highs[i].score);
  1199. X    pw_text (pw, HIGHS_X+270, HIGHS_Y+i*SPACING, PIX_SRC, bigfont, s);
  1200. X    }
  1201. X    pw_batch_off (pw);
  1202. X}
  1203. X
  1204. X
  1205. X#ifndef HIGHSCOREFILE
  1206. X#define HIGHSCOREFILE suntetris.hs
  1207. X#endif HIGHSCOREFILE
  1208. X
  1209. X/* The file locking here isn't foolproof */
  1210. X/* We have an unsecured highscore file */
  1211. Xvoid
  1212. Xupdate_hs (score, level)
  1213. Xint score, level;
  1214. X{
  1215. X    FILE *fp;
  1216. X    int i, j;
  1217. X    struct passwd *passwd = getpwuid (getuid ());
  1218. X
  1219. X    if ((fp = fopen (HIGHSCOREFILE, "r")) != NULL)  {    /* read old scores */
  1220. X    lockf (fileno (fp), F_LOCK, 0);
  1221. X    while (i < 10 && (fscanf(fp, "%s %d %d", highs[i].name,
  1222. X              &highs[i].level, &highs[i].score) != EOF))  i++;
  1223. X    fclose (fp);
  1224. X    }
  1225. X    for (i = 10; i > 0 && score > highs[i-1].score; i--) ;
  1226. X    if (i > 9)  return;
  1227. X    if ((fp = fopen (HIGHSCOREFILE, "w")) == NULL)  return;
  1228. X    lockf (fileno (fp), F_LOCK, 0);
  1229. X    for (j = 9; j > i; j--)  {
  1230. X    strcpy (highs[j].name, highs[j-1].name);
  1231. X    highs[j].level = highs[j-1].level;
  1232. X    highs[j].score = highs[j-1].score;
  1233. X    }
  1234. X    strcpy (highs[i].name, passwd->pw_name);
  1235. X    highs[i].level = level;
  1236. X    highs[i].score = score;
  1237. X    for (i = 0; i < 10; i++)
  1238. X    fprintf (fp, "%s %d %d\n", highs[i].name, highs[i].level,
  1239. X         highs[i].score);
  1240. X    fclose (fp);
  1241. X}
  1242. END_OF_FILE
  1243. if test 15955 -ne `wc -c <'suntetris_pw.c'`; then
  1244.     echo shar: \"'suntetris_pw.c'\" unpacked with wrong size!
  1245. fi
  1246. # end of 'suntetris_pw.c'
  1247. fi
  1248. echo shar: End of archive 1 \(of 1\).
  1249. cp /dev/null ark1isdone
  1250. MISSING=""
  1251. for I in 1 ; do
  1252.     if test ! -f ark${I}isdone ; then
  1253.     MISSING="${MISSING} ${I}"
  1254.     fi
  1255. done
  1256. if test "${MISSING}" = "" ; then
  1257.     echo You have the archive.
  1258.     rm -f ark[1-9]isdone
  1259. else
  1260.     echo You still need to unpack the following archives:
  1261.     echo "        " ${MISSING}
  1262. fi
  1263. ##  End of shell archive.
  1264. exit 0
  1265.